﻿using System;
using System.Collections.Generic;
using System.Text;
using ITAP.Core.Modelling.Primitives;
using System.Drawing;
using ITAP.Core.Modelling;

namespace ITAP.ShprossesBuilder.Modelling.Components
{
    /// <summary>
    /// Компонент, имеющий концы.
    /// </summary>
    public interface IEndedComponent : IComponent
    {
        /// <summary>
        /// Начальная точка компонента.
        /// </summary>
        ModelPoint StartPoint { get; set; }
        /// <summary>
        /// Конечная точка компонента.
        /// </summary>
        ModelPoint EndPoint { get; set; }
        /// <summary>
        /// Начальный угол реза компонента.
        /// </summary>
        Angle StartCutAngle { get; set; }
        /// <summary>
        /// Конечный угол реза компонента.
        /// </summary>
        Angle EndCutAngle { get; set; }
        /// <summary>
        /// Ширина компонента.
        /// </summary>
        double Width { get; set; }
        /// <summary>
        /// Длина компонента.
        /// </summary>
        double Length { get; set; }
        /// <summary>
        /// Ссылка на компонент, приконнекченный к началу компонента.
        /// </summary>
        IComponent StartConnectedComponent { get; set; }
        /// <summary>
        /// Ссылка на компонент, приконнекченный к концу компонента.
        /// </summary>
        IComponent EndConnectedComponent { get; set; }
        /// <summary>
        /// Коннект одного из концов компонента к компоненту в аргументе. Нельзя использовать отдельно, для коннекта и дисконнекта компонент
        /// необходимо использовать <see cref="ConnectionProvider"/>.
        /// </summary>
        /// <param name="component">Компонент, к которому надо приконнектиться.</param>
        /// <param name="endForConnect">Конец данного компонента, который должен приконнектиться к компоненту в аргументе.</param>
        /// <returns>Ссылка на компонент, к которому был совершён коннект. Если данный компонент простой, то вернётся this, иначе вернётся
        /// ссылка на внутренний компонент данного компонента, к которому был совершён коннект.</returns>
        IComponent ConnectTo(IComponent component, EndType endForConnect);
        /// <summary>
        /// Если к концу компонента пытается приконнектиться другой компонент, то необходимо решать, что делать - 
        /// отказывать ему в коннекте или приконнекчивать, отконнекчивая приконнекченный. Этот список определяет 
        /// порядок "важности" приконнекчивающихся компонентов - те, кто ближе к началу, имеют преимущество перед
        /// теми, кто ближе к концу.
        /// </summary>
        List<Type> ConnectPriorityForEnds { get; }
        /// <summary>
        /// Перемещение начальной точки компонента в указанную точку.
        /// </summary>
        /// <param name="destination">Точка, в которую надо переместить начальную точку компонента.</param>
        void MoveStartPointTo(ModelPoint destination);
        /// <summary>
        /// Перемещение конечной точки компонента в указанную точку.
        /// </summary>
        /// <param name="destination">Точка, в которую надо переместить конечную точку компонента.</param>
        void MoveEndPointTo(ModelPoint destination);
        /// <summary>
        /// Перемещение начальной точки компонента в указанную точку, учитывая ограничивающий прямоугольник.
        /// </summary>
        /// <param name="destination">Точка, в которую надо переместить начальную точку компонента.</param>
        /// <param name="boundingRectangle">Ограничивающий прямоугольник, определяющий границы, в которых можно двигать начальную точку компонента.</param>
        void MoveStartPointTo(ModelPoint destination, RectangleF boundingRectangle, bool allowOutOfRectangleForOneEnd);
        /// <summary>
        /// Перемещение конечной точки компонента в указанную точку, учитывая ограничивающий прямоугольник.
        /// </summary>
        /// <param name="destination">Точка, в которую надо переместить конечную точку компонента.</param>
        /// <param name="boundingRectangle">Ограничивающий прямоугольник, определяющий границы, в которых можно двигать конечную точку компонента.</param>
        void MoveEndPointTo(ModelPoint destination, RectangleF boundingRectangle, bool allowOutOfRectangleForOneEnd);
        /// <summary>
        /// Задание высоты компонента (например, высоты арки), учитывая ограничивающий прямоугольник.
        /// </summary>
        /// <param name="height">Высота компонента.</param>
        /// <param name="boundingRectangle">Ограничивающий прямоугольник, определяющий допустимые границы положения компонента.</param>
        void SetHeight(double height, RectangleF boundingRectangle);
        /// <summary>
        /// Задание высоты компонента (например, высоты арки).
        /// </summary>
        double Height { get; set; }
    }


}
